package com.jurgenromeijn.pokedex;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.ByteArrayBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONObject;
import org.json.JSONTokener;

import android.app.Activity;
import android.content.Intent;
import android.graphics.*;
import android.os.Bundle;
import android.os.StrictMode;
import android.util.Log;
import android.view.*;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.view.SurfaceView;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.LinearInterpolator;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PictureCallback;

public class PokedexActivity extends Activity implements SurfaceHolder.Callback, OnClickListener, PictureCallback, AutoFocusCallback {
	/** Called when the activity is first created. */
	private SurfaceView _cameraView;
	private SurfaceHolder _cameraViewHolder;
	private Camera _camera;
	private ImageView _cameraIndicator;
	private Animation _cameraIndicatorAnimation;
	private boolean _scanning = false;
			
	public static String accessKey = "83d888e4-a370-4b95-bda3-3479d98427b8";
	public static String secretKey = "6CMMEZDkCIwbzO3CvZMz7qPZwXW0rdMc5PhSlwz1";
	public static String apiAddress = "https://query-api.kooaba.com/v4/query";
	public static String boundary = "51768e7298680";

    public static final int DRAW_RESULT_BITMAP = 10;
	private ImageButton _scanButton;
    //private Handler mUiHandler;
    //private OpenCVWorker mWorker;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        ImageView view = (ImageView)findViewById(android.R.id.home);
        view.setPadding(0, 0, 16, 0);
        
        setupCameraView();
        setClickListeners();
    }
    
    @Override
    public void onDestroy()
    {
        if (_camera != null)
        {
        	_camera.stopPreview();
            _camera.setPreviewCallback(null);
            _camera.release();
            _camera = null;
        }
        super.onDestroy();
    }
    
	@Override
	public void onClick(View v) {
		switch(v.getId()) {
			case R.id.scanButton:
				if(!_scanning) {
					_camera.autoFocus(this);
					_scanning = true;
					
					Animation rotation = AnimationUtils.loadAnimation(this, R.anim.clockwise_rotation);
					rotation.setRepeatCount(Animation.INFINITE);
					_scanButton.startAnimation(rotation);
				}
				break;
			default:
				// Do nothing
				break;
		}
	}
	
	private void startIndicatorBlinking()
	{
		if(_cameraIndicator == null) {
	        _cameraIndicator = (ImageView)findViewById(R.id.cameraIndicator);
	        _cameraIndicatorAnimation = new AlphaAnimation(0, 1);
	        _cameraIndicatorAnimation.setDuration(500);
	        _cameraIndicatorAnimation.setInterpolator(new LinearInterpolator());
	        _cameraIndicatorAnimation.setRepeatCount(Animation.INFINITE);
	        _cameraIndicatorAnimation.setRepeatMode(Animation.REVERSE);
		}
		_cameraIndicator.setAlpha(new Float(1));
		_cameraIndicator.startAnimation(_cameraIndicatorAnimation);
	}
	
	private void stopIndicatorBlinking()
	{
		_cameraIndicator.clearAnimation();
		_cameraIndicator.setAlpha(new Float(0));
	}
	
	@Override
	public void onAutoFocus(boolean success, Camera camera) {
		// TODO Auto-generated method stub
		_camera.takePicture(null, null, this);
        stopIndicatorBlinking();
	}
	
	@Override
	public void onPictureTaken(byte[] data, Camera camera) {						
		String pokemon = findPokemon(data);
		showPokemon(pokemon);
		
		try {
	        startIndicatorBlinking();
			_scanButton.clearAnimation();
			_camera.setPreviewDisplay(_cameraViewHolder);
	        _camera.startPreview();
	        _scanning = false;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
		
	private String findPokemon(byte[] data)
	{
		HttpResponse response = doQueryRequest(data);
		try {
			BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
			String json = reader.readLine();
			JSONTokener tokener = new JSONTokener(json);
			JSONObject responseObject = new JSONObject(tokener);
			return responseObject.getJSONArray("results").getJSONObject(0).getString("reference_id");
		} catch (Exception e) {
			// TODO: handle exception
		}
		return "";
	}
	
	private void showPokemon(String pokemon)
	{
		Intent pokedexEntry = new Intent(this, EntryDialog.class);
		pokedexEntry.putExtra("pokemon", pokemon);
		startActivity(pokedexEntry);
		/*AlertDialog dialog = new AlertDialog.Builder(this).create();
		dialog.setTitle("resultaat scan");
		dialog.setIcon(R.drawable.ic_launcher);
		dialog.setMessage(pokemon);
		dialog.show();*/
	}
	
	private HttpResponse doQueryRequest(byte[] data)
	{
        try {
    		// Todo: remove dirty hack, network on main thread
    		StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
    		StrictMode.setThreadPolicy(policy); 

    		
    		// Create content
    		MultipartEntity content = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE, boundary, Charset.defaultCharset());
    		content.addPart("image", new ByteArrayBody(data, "pokedexphoto.jpg"));
                        
    		// Build request
    		HttpClient client = new DefaultHttpClient();
    		HttpPost request = new HttpPost(apiAddress);
            request.setEntity(content);
            request.addHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
            request.addHeader("Authorization", "Token " + secretKey);

            // Send request
			HttpResponse response = client.execute(request);
			return response;
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        return null;
	}
		    
    private void setupCameraView()
    {
        _cameraView = (SurfaceView) findViewById(R.id.cameraView);
        _cameraViewHolder = _cameraView.getHolder();
        
        _cameraViewHolder.addCallback(this);
    }
    
    public void setClickListeners()
    {
    	_scanButton = (ImageButton)findViewById(R.id.scanButton);
    	_scanButton.setOnClickListener(this);
    }
    
    private void setupCamera()
    {
    	_camera = Camera.open();
    	Log.d("pokedex", _camera.toString());
        
        Camera.Parameters parameters = _camera.getParameters();
        parameters.setPictureFormat(ImageFormat.JPEG);
        parameters.setRotation(90);
        _camera.setParameters(parameters);
        _camera.setDisplayOrientation(90);
    }
    
    @Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		// TODO Auto-generated method stub
        setupCamera();
		try {
			_camera.setPreviewDisplay(_cameraViewHolder);
	        _camera.startPreview();
	        startIndicatorBlinking();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		// TODO Auto-generated method stub
        if (_camera != null)
        {
        	_camera.stopPreview();
            _camera.setPreviewCallback(null);
            _camera.release();
            _camera = null;
            stopIndicatorBlinking();
        }
	}
}